<?php
/**
$CK = A('CheckInput');
$id = $CK->in($CnName,$name,$CheckType,$default,$LengMin,$LengMax);

*in方法使用说明
*@param $CnName  字符串,中文名,出错时提示用
*@param $name 字符串,传入参数,可用 get.id或post.id,put.id等，  参考thinkphp的I方法
*@param $CheckType 字符串,过滤方法,
*@param $default(可选) 字符串,默认值
*@param $LengMin(可选) 数字,最短长度,为0时不限制
*@param $LengMax(可选) 数字,最大长度,为0时不限制

---$CheckType可用值:
intval 0或正整数
date   日期 如:2014-05-02
time   时间 如:16:25:00
datetime 长时间 如:2014-05-02 16:25:00
password 密码 自动md5后，取前28位字符
bool   是/否 除输入为0外, 其它都返回 1;
float  小数 如:1253.123, 不限制小数点多少位
float(8,2) 小数,整数8位,小数2位,8和2可改
email 邮箱格式,（后期加防注入)
saveimage 上传图片,最短长度不为0，即为必须上传，现在每个页面仅支持上传一个图片
enstr  仅为字母,
numstr 仅为数字,
ennumstr  字母,数字,下划线,(防注入)
cnennumstr  中文,英文,数字,下划线,(即不允许有特殊字符)(防注入)
string 任意字符串,后期加入防sql注入,防xss,防javascript,尽量不要使用这种方式过滤
htcontent 内容型,后台在线内容编辑器专用,前台内容编辑器也不能使用,其它地方尽量不要使用,防sql注入,不防javascript

例：(取多个值时，只A一次即可)
$CK  = A('CheckInput');
$id  = $CK->in('id变量','get.id','intval','',0,3);
$str = $CK->in('密码','get.str','password','',1);
*/
function CheckInputFunc($CnName, $name, $CheckType, $default = NULL, $LengMin = 0, $LengMax = 0) {
	$res ['ok'] = true;
	$res ['error'] = '';
	$res ['data'] = NULL;
	if (strpos ( $name, '.' )) { // 指定参数来源
		list ( $method, $name ) = explode ( '.', $name, 2 );
	} else { // 默认为自动判断
		$method = 'param';
	}
	switch (strtolower ( $method )) {
		case 'get' :
			$input = & $_GET;
			break;
		case 'post' :
			$input = & $_POST;
			break;
		case 'put' :
			parse_str ( file_get_contents ( 'php://input' ), $input );
			break;
		case 'param' :
			switch ($_SERVER ['REQUEST_METHOD']) {
				case 'POST' :
					$input = $_POST;
					break;
				case 'PUT' :
					parse_str ( file_get_contents ( 'php://input' ), $input );
					break;
				default :
					$input = $_GET;
			}
			break;
		case 'path' :
			$input = array ();
			if (! empty ( $_SERVER ['PATH_INFO'] )) {
				$depr = C ( 'URL_PATHINFO_DEPR' );
				$input = explode ( $depr, trim ( $_SERVER ['PATH_INFO'], $depr ) );
			}
			break;
		case 'request' :
			$input = & $_REQUEST;
			break;
		case 'session' :
			$input = & $_SESSION;
			break;
		case 'cookie' :
			$input = & $_COOKIE;
			break;
		case 'server' :
			$input = & $_SERVER;
			break;
		case 'globals' :
			$input = & $GLOBALS;
			break;
		case 'data' :
			$input = & $datas;
			break;
		case 'file' :
			$input = & $_FILES;
			break;
		default :
			return NULL;
	}
	if (empty ( $name )) { // 获取全部变量
		$res ['ok'] = false;
		$res ['error'] = '方法传入参数错误！';
		return $res;
	} elseif (isset ( $input [$name] )) { // 取值操作
		$data = $input [$name];
	} else { // 变量默认值
		$data = isset ( $default ) ? $default : NULL;
	}
	
	if ($LengMin != 0) {
		if ($data == '' || $data == NULL) {
			$res ['ok'] = false;
			$res ['error'] = "请填写【 $CnName 】！";
			return $res;
		}
		if (mb_strlen ( $data ,'utf8' ) < $LengMin) {
			$res ['ok'] = false;
			$res ['error'] = "【 $CnName 】太短,请重输！";
			return $res;
		}
	} else {
		if ($data == '' || $data == NULL) {
			$res ['ok'] = true;
			$res ['data'] = $data;
			return $res;
		}
	}
	if ($LengMax != 0) {
		if (mb_strlen ( $data ,'utf8') > $LengMax) {
			$res ['ok'] = false;
			$res ['error'] = "【 $CnName 】太长,请重输！";
			return $res;
		}
	}

	$CKT = new CheckInput();
	$CKT->CnName = $CnName;
	$CKT->CheckType = $CheckType;
	$CKT->data = $data;
	$CKT->LengMin = $LengMin;
	
	return $CKT->check ();
}

class CheckInput{
	var $CnName; // 中文名
	var $CheckType; // 过滤类型
	var $data; // 要过滤的变量
	var $res; // 反回的数组
	var $LengMin;
	var $postfilter = "<[^>]*?=[^>]*?&#[^>]*?>|\\b(alert\\(|confirm\\(|expression\\(|prompt\\()|<[^>]*?\\b(onerror|onmousemove|onload|onclick|onmouseover)\\b[^>]*?>|\\b(and|or)\\b\\s*?([\\(\\)'\"\\d]+?=[\\(\\)'\"\\d]+?|[\\(\\)'\"a-zA-Z]+?=[\\(\\)'\"a-zA-Z]+?|>|<|\s+?[\\w]+?\\s+?\\bin\\b\\s*?\(|\\blike\\b\\s+?[\"'])|\\/\\*.+?\\*\\/|<\\s*script\\b|\\bEXEC\\b|UNION.+?SELECT|UPDATE.+?SET|INSERT\\s+INTO.+?VALUES|(SELECT|DELETE).+?FROM|(CREATE|ALTER|DROP|TRUNCATE)\\s+(TABLE|DATABASE)";
	var $htcontentfilter = "<[^>]*?=[^>]*?&#[^>]*?>|\\b(alert\\(|confirm\\(|expression\\(|prompt\\()|<[^>]*?\\b(onerror|onmousemove|onload|onclick|onmouseover)\\b[^>]*?>|\\b(and|or)\\b\\s*?([\\(\\)'\"\\d]+?=[\\(\\)'\"\\d]+?|[\\(\\)'\"a-zA-Z]+?=[\\(\\)'\"a-zA-Z]+?|>|<|\s+?[\\w]+?\\s+?\\bin\\b\\s*?\(|\\blike\\b\\s+?[\"'])|\\/\\*.+?\\*\\/|<\\s*scriiipt\\b|\\bEXEC\\b|UNION.+?SELECT|UPDATE.+?SET|INSERT\\s+INTO.+?VALUES|(SELECT|DELETE).+?FROM|(CREATE|ALTER|DROP|TRUNCATE)\\s+(TABLE|DATABASE)";
	function __construct() {
	}
	function check() {
		switch ($this->CheckType) {
			case 'intval' :
				$this->_intval ();
				break;
			case 'date' :
				$this->_date ();
				break;
			case 'time' :
				$this->_time ();
				break;
			case 'datetime' :
				$this->_datetime ();
				break;
			case 'password' :
				$this->_password ();
				break;
			case 'string' :
				$this->_string ();
				break;
			case 'enstr' :
				$this->_enstr ();
				break;
			case 'numstr' :
				$this->_numstr ();
				break;
			case 'ennumstr' :
				$this->_ennumstr ();
				break;
			case 'cnennumstr' :
				$this->_cnennumstr ();
				break;
			case 'htcontent' :
				$this->_htcontent ();
				break;
			case 'float' :
				$this->_float ();
				break;
			case 'bool' :
				$this->_bool ();
				break;
			case 'email' :
				$this->_email ();
				break;
			case 'saveimage' :
				$this->_saveimage ();
				break;
			case 'uploadFile' :
				$this->_uploadFile();
				break;
			case 'shenfenzheng':
				$this->_shenfenzheng();
				break;
			default :
				// 处理特殊值 如 float(11,2)
				if ((strpos ( $this->CheckType, 'float' )) !== false) {
					$this->_floatex ();
				} elseif (false) {
				} else {
					$this->res ['ok'] = false;
					$this->res ['error'] = '函数过滤方法填写错误';
				}
		}
		return $this->res;
	}
	private function _saveimage() {
		if (C ( 'CheckInputsaveimage' ) == NULL) {
			// echo '===================';
			$upload = new \Think\Upload (); // 实例化上传类
			$upload->autoSub = true; // 是否使用子目录保存上传文件
			$upload->subType = 'date'; // 子目录创建方式，默认为hash，可以设置为hash或者date
			$upload->dateFormat = 'd'; // 子目录方式为date的时候指定日期格式
			$upload->maxSize = 1887437; // 设置附件上传大小
			$upload->exts = array (
					'jpg',
					'gif',
					'png',
					'jpeg' 
			); // 设置附件上传类型
			$upload->rootPath = 'uploads'; // 设置附件上传根目录
			$upload->savePath = '/images/' . date ( 'Y-m', time () ) . '/'; // 设置附件上传目录
			$upload->replace = true;
			// $upload->mimes = array('image/jpeg','image/jpg','image/gif','image/png'); //允许上传的文件类型（留空为不限制）
			// $upload->callback=true;
			$info = $upload->upload ();
			if (! $info) { // 上传错误提示错误信息
				$error = $upload->getError ();
				if (strpos ( $error, '没有文件被上传' ) !== false) {
					// echo '没有文件上传';
				} else {
					$this->res ['ok'] = false;
					$this->res ['error'] = '【 ' . $this->CnName . ' 】' . $error;
					return 0;
				}
			}
			C ( 'CheckInputsaveimage', $info );
		} else {
			$info = C ( 'CheckInputsaveimage' );
		}
		
		// dump($info);
		// dump($this->data);
		
		$savefile = $info [$this->data] ["savepath"] . $info [$this->data] ["savename"];
		
		if ($savefile == '' || $savefile == null) {
			$savefile = '';
			if ($this->LengMin > 0) {
				$this->res ['ok'] = false;
				$this->res ['error'] = '【 ' . $this->CnName . ' 】必须上传,请重输！';
				return 0;
			}
		} else {
			// $savefile='/uploads'.$savefile;
			$savefile = 'uploads' . $savefile;
		}
		
		$this->res ['ok'] = true;
		$this->res ['data'] = $savefile;
		
		// die();
		// 保存表单数据 包括附件数据
		// return $savePath.$info[0]['savename']; // 保存上传的照片根据需要自行组装
	}
	
	/*
	 * 上传文件($_File)
	 */
	private function _uploadFile(){
		$upload = new \Think\Upload (); // 实例化上传类
		$upload->autoSub = true; // 是否使用子目录保存上传文件
		$upload->subType = 'date'; // 子目录创建方式，默认为hash，可以设置为hash或者date
		$upload->dateFormat = 'd'; // 子目录方式为date的时候指定日期格式
		$upload->maxSize = 1887437; // 设置附件上传大小
		$upload->exts = array (
				'jpg',
				'gif',
				'png',
				'jpeg'
		); // 设置附件上传类型
		$upload->rootPath = 'uploads'; // 设置附件上传根目录
		$upload->savePath = '/images/' . date ( 'Y-m', time () ) . '/'; // 设置附件上传目录
		$upload->replace = true;
		$info = $upload->upload ();
		if (! $info) { // 上传错误提示错误信息
			$error = $upload->getError ();
			if (strpos ( $error, '没有文件被上传' ) !== false) {
				// echo '没有文件上传';
			} else {
				$this->res ['ok'] = false;
				$this->res ['error'] = '【 ' . $this->CnName . ' 】' . $error;
				return 0;
			}
		}
		
		$savefile = $info [key($info)] ["savepath"] . $info [key($info)] ["savename"];
		
		if ($savefile == '' || $savefile == null) {
			$savefile = '';
			if ($this->LengMin > 0) {
				$this->res ['ok'] = false;
				$this->res ['error'] = '【 ' . $this->CnName . ' 】必须上传,请重输！';
				return 0;
			}
		} else {
			$savefile = 'uploads' . $savefile;
		}
		
		$this->res ['ok'] = true;
		$this->res ['data'] = $savefile;
		
	}
	
	private function _htcontent() {
		// if (preg_match("/".$this->htcontentfilter."/is",$this->data)==1){
		// $this->res['ok']=false;
		// $this->res['error']='【 '.$this->CnName.' 】包含非法字符,请重输！';
		// return 0;
		// }
		$this->res ['ok'] = true;
		$this->res ['data'] = ($this->data);
	}
	private function _cnennumstr() {
		if (preg_match ( "/" . $this->postfilter . "/is", $this->data ) == 1) {
			$this->res ['ok'] = false;
			$this->res ['error'] = '【 ' . $this->CnName . ' 】包含非法字符,请重输！';
			return 0;
		}
		// if(!preg_match("/^[0-9a-zA-Z_]{1,}$/",$this->data)){
		// if(!preg_match("/^[\x{4e00}-\x{9fa5}]+$/u",$this->data)){
		if (! preg_match ( "/^[\x80-\xff_a-zA-Z0-9]+$/", $this->data )) {
			$this->res ['ok'] = false;
			$this->res ['error'] = '【 ' . $this->CnName . ' 】不能包含特殊字符,请重输！';
			return 0;
		}
		$this->res ['ok'] = true;
		$this->res ['data'] = ($this->data);
	}
	private function _string() {
		if (preg_match ( "/" . $this->postfilter . "/is", $this->data ) == 1) {
			$this->res ['ok'] = false;
			$this->res ['error'] = '【 ' . $this->CnName . ' 】包含非法字符,请重输！';
			return 0;
		}
		$this->res ['ok'] = true;
		$this->res ['data'] = ($this->data);
	}
	private function _ennumstr() {
		if (preg_match ( "/" . $this->postfilter . "/is", $this->data ) == 1) {
			$this->res ['ok'] = false;
			$this->res ['error'] = '【 ' . $this->CnName . ' 】包含非法字符,请重输！';
			return 0;
		}
		if (! preg_match ( "/^[0-9a-zA-Z_]{1,}$/", $this->data )) {
			$this->res ['ok'] = false;
			$this->res ['error'] = '【 ' . $this->CnName . ' 】只能输入数字,请重输！';
			return 0;
		}
		$this->res ['ok'] = true;
		$this->res ['data'] = $this->data;
	}
	private function _numstr() {
		if (! preg_match ( "/^[-]{0,1}[0-9]{1,}$/", $this->data )) {
			$this->res ['ok'] = false;
			$this->res ['error'] = '【 ' . $this->CnName . ' 】只能输入整数,请重输！';
			return 0;
		}
		$this->res ['ok'] = true;
		$this->res ['data'] = $this->data;
	}
	private function _enstr() {
		if (preg_match ( "/" . $this->htcontentfilter . "/is", $this->data ) == 1) {
			$this->res ['ok'] = false;
			$this->res ['error'] = '【 ' . $this->CnName . ' 】包含非法字符,请重输！';
			return 0;
		}
		if (! preg_match ( "/^[a-zA-Z]{1,}$/", $this->data )) {
			$this->res ['ok'] = false;
			$this->res ['error'] = '【 ' . $this->CnName . ' 】只能输入英文字母,请重输！';
			return 0;
		}
		$this->res ['ok'] = true;
		$this->res ['data'] = $this->data;
	}
	private function _email() {
		if (preg_match ( "/" . $this->postfilter . "/is", $this->data ) == 1) {
			$this->res ['ok'] = false;
			$this->res ['error'] = '【 ' . $this->CnName . ' 】包含非法字符,请重输！';
			return 0;
		}
		if (! preg_match ( "/^[_.0-9a-z-]+@([0-9a-z][0-9a-z-]+.)+[a-z]{2,3}$/", $this->data )) {
			$this->res ['ok'] = false;
			$this->res ['error'] = '【 ' . $this->CnName . ' 】格式错误,请重输！';
			return 0;
		}
		$this->res ['ok'] = true;
		$this->res ['data'] = $this->data;
	}
	private function _floatex() {
		$pa = '/float\((.*),(.*)\)/';
		preg_match_all ( $pa, $this->CheckType, $ma );
		// dump($ma[1][0]);
		// dump($ma[2][0]);
		if (! preg_match ( "/^[-]{0,1}\d{0," . $ma [1] [0] . "}\.{0,1}(\d{0," . $ma [2] [0] . "})?$/", $this->data )) {
			$this->res ['ok'] = false;
			$this->res ['error'] = '【 ' . $this->CnName . ' 】只能输入整数或小数,请重输！';
			return 0;
		}
		$this->res ['ok'] = true;
		$this->res ['data'] = $this->data;
	}
	private function _float() {
		try {
			$str = ( double ) ($this->data);
		} catch ( Exception $e ) {
			$this->res ['ok'] = false;
			$this->res ['error'] = '【 ' . $this->CnName . ' 】只能输入整数或小数,请重输！';
			return 0;
		}
		if (( string ) ($str) != $this->data) {
			$this->res ['ok'] = false;
			$this->res ['error'] = '【 ' . $this->CnName . ' 】只能输入整数或小数,请重输！';
			return 0;
		}
		$this->res ['ok'] = true;
		$this->res ['data'] = $this->data;
	}
	private function _bool() {
		if ($this->data == 0) {
			$this->res ['data'] = 0;
		} else {
			$this->res ['data'] = 1;
		}
		$this->res ['ok'] = true;
	}
	private function _password() {
		$this->res ['ok'] = true;
		$this->res ['data'] = substr ( md5 ( $this->data ), 0, 28 );
		// $this->res ['data'] = md5 ( $this->data );
	}
	private function _intval() {
		if (! preg_match ( "/^[-]{0,1}[0-9]{1,}$/", $this->data )) {
			$this->res ['ok'] = false;
			$this->res ['error'] = '【 ' . $this->CnName . ' 】只能输入整数,请重输！';
			return 0;
		}
		$this->res ['ok'] = true;
		$this->res ['data'] = $this->data;
		/*
		 * if( strval($this->data) == strval(intval($this->data)) ){ $this->res['ok']=true; $this->res['data']=$this->data; }else{ $this->res['ok']=false; $this->res['error']='【 '.$this->CnName.' 】只能输入数字,请重输！'; }
		 */
	}
	private function _date() {
		if (! preg_match ( '/^[0-9]{4}-[0-9]{1,2}-[0-9]{1,2}$/', $this->data )) {
			if (! preg_match ( '/^[0-9]{4}-[0-9]{1,2}-[0-9]{1,2}$/', $this->data )) {
				$this->res ['ok'] = false;
				$this->res ['error'] = '【 ' . $this->CnName . ' 】格式错误,请重输！';
				return 0;
			}
		}
		if (strtotime ( $this->data ) === false) {
			$this->res ['ok'] = false;
			$this->res ['error'] = '【 ' . $this->CnName . ' 】格式错误,请重输！';
			return 0;
		}
		$this->res ['ok'] = true;
		$this->res ['data'] = $this->data;
	}
	private function _time() {
		if (! preg_match ( '/^[0-2]{0,1}[0-9]{1}[:]{1}[0-5]{0,1}[0-9]{1}[:]{1}[0-5]{0,1}[0-9]{1}$/', $this->data )) {
			if (! preg_match ( '/^[0-2]{0,1}[0-9]{1}[:]{1}[0-5]{0,1}[0-9]{1}$/', $this->data )) {
				$this->res ['ok'] = false;
				$this->res ['error'] = '【 ' . $this->CnName . ' 】格式错误,请重输！';
				return 0;
			}
		}
		if (strtotime ( $str_tmp ) === false) {
			$this->res ['ok'] = false;
			$this->res ['error'] = '【 ' . $this->CnName . ' 】格式错误,请重输！';
			return 0;
		}
		$this->res ['ok'] = true;
		$this->res ['data'] = $this->data;
	}
	private function _datetime() {
		if (! preg_match ( '/^[0-9]{4}-[0-9]{1,2}-[0-9]{1,2} [0-9]{1,2}:[0-9]{1,2}:[0-9]{1,2}$/', $this->data )) {
			if (! preg_match ( '/^[0-9]{4}-[0-9]{1,2}-[0-9]{1,2} [0-9]{1,2}:[0-9]{1,2}$/', $this->data )) {
				$this->res ['ok'] = false;
				$this->res ['error'] = '【 ' . $this->CnName . ' 】格式错误,请重输！';
				return 0;
			}
		}
		if (strtotime ( $this->data ) === false) {
			$this->res ['ok'] = false;
			$this->res ['error'] = '【 ' . $this->CnName . ' 】格式错误,请重输！';
			return 0;
		}
		$this->res ['ok'] = true;
		$this->res ['data'] = $this->data;
	}
	
	private function _shenfenzheng(){
		if(ck_shengfenzheng($this->data)){
			$this->res ['ok'] = true;
			$this->res ['data'] = $this->data;			
		}else{
			$this->res ['ok'] = false;
			$this->res ['error'] = '【 ' . $this->CnName . ' 】格式错误,请重输！';
			return 0;
		}
	}
}

/**
 * 加密解密函数
 * $operation DECODE ENCODE
 * 
 */
function authcode($string, $operation = 'DECODE', $key = '', $expiry = 0) {

	$ckey_length = 4;

	//$key = md5($key ? $key : UC_KEY);
	$key = md5($key);
	$keya = md5(substr($key, 0, 16));
	$keyb = md5(substr($key, 16, 16));
	$keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length): substr(md5(microtime()), -$ckey_length)) : '';

	$cryptkey = $keya.md5($keya.$keyc);
	$key_length = strlen($cryptkey);

	$string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0).substr(md5($string.$keyb), 0, 16).$string;
	$string_length = strlen($string);

	$result = '';
	$box = range(0, 255);

	$rndkey = array();
	for($i = 0; $i <= 255; $i++) {
		$rndkey[$i] = ord($cryptkey[$i % $key_length]);
	}

	for($j = $i = 0; $i < 256; $i++) {
		$j = ($j + $box[$i] + $rndkey[$i]) % 256;
		$tmp = $box[$i];
		$box[$i] = $box[$j];
		$box[$j] = $tmp;
	}

	for($a = $j = $i = 0; $i < $string_length; $i++) {
		$a = ($a + 1) % 256;
		$j = ($j + $box[$a]) % 256;
		$tmp = $box[$a];
		$box[$a] = $box[$j];
		$box[$j] = $tmp;
		$result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));
	}

	if($operation == 'DECODE') {
		if((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26).$keyb), 0, 16)) {
			return substr($result, 26);
		} else {
			return '';
		}
	} else {
		return $keyc.str_replace('=', '', base64_encode($result));
	}

}

/**
 * 添加规则
 * @param $str 规则标识 $pid 所属模块 $des 描述说明
 * @author 黄药师 <46914685@qq.com> 20150126
 */
function rulAutoAdd($str,$pid,$des=''){
	
	if(empty($str)||empty($pid)){
		$return['message']="参数不能为空!";
		$return['status']=false;
		return $return;
	}
	//查找规则标识是否存在	
	$name=M()->table(C('DB_DEPOT.DB_NAME').'.'.C('DB_PRS').'auth_rule')->where(array('name'=>$str))->cache('ruleAutoAdd'.$str,300)->field('name')->count();
	if($name){
		$return['message']="规则标识已经存在!";
		$return['status']=false;
		return $return;
	}
	//添加规则
	$id=M()->table(C('DB_DEPOT.DB_NAME').'.'.C('DB_PRS').'auth_rule')->add(array('name'=>$str,'pid'=>$pid,'title'=>$des));
	if($id){
		$return['message']="规则标识添加成功!";
		$return['status']=true;
		S('ruleAutoAdd'.$str,null);//删除缓存,防止出错
	}else{
		$return['message']="规则标识添加失败!";
		$return['status']=false;
	}	
	return $return;
}

	/**
      * 权限验证
      * @param rule string|array  需要验证的规则列表,支持逗号分隔的权限规则或索引数组
      * @param uid  int           认证用户的id
      * @param string mode        执行check的模式
      * @param relation string    如果为 'or' 表示满足任一条规则即通过验证;如果为 'and'则表示需满足所有规则才能通过验证
      * @return boolean           通过验证返回true;失败返回false
      * @return author            黄药师		46914685@qq.com
     */
	function authCheck($rule,$uid,$type=1, $mode='url', $relation='or'){
		//超级管理员跳过验证
		$auth=new \Think\Auth();
		//获取当前uid所在的角色组id
		$groups=$auth->getGroups($uid);
		session('gid',$groups[0]['group_id']);//角色组id
		session('gname',$groups[0]['title']);//角色组名称
		// dump($uid);
		// dump($groups);
		// dump($rule);
		// dump(C('NO_AUTH_RULES'));
		//设置的是一个用户对应一个角色组,所以直接取值.如果是对应多个角色组的话,需另外处理
		if(in_array($groups[0]['group_id'], C('ADMINISTRATOR'))){
			return true;
		}else if(in_array($rule, C('NO_AUTH_RULES'))){
			return true;
		}else{
			return $auth->check($rule,$uid,$type,$mode,$relation)?true:false;
		}
	}

	//获取模型列表数据
	//$table 表名
	//$map 查询条件
	function getTable($table,$map,$page,$rows,$sort,$order,$status=NULL){
		
		$m=M($table,C('DB_PRS'),C('DB_DEPOT'));
		if($status==NULL){
			$map['status']=array('neq',-1);//未删除
		}else{
			$map['status']=$status;
		}

		$count=$m->where($map)->count();
		$info=$m->where($map)->page($page,$rows)->order($sort.' '.$order)->select();
		// echo $m->getlastsql();
		foreach($info as $k=>$v){
			if(!empty($v['update_time'])){
				$info[$k]['update_time']=date("Y-m-d H:i:s",$v['update_time']);
			}
			if(!empty($v['examine_time'])){
				$info[$k]['examine_time']=date("Y-m-d H:i:s",$v['examine_time']);
			}
			if(!empty($v['add_time'])){
				$info[$k]['add_time']=date("Y-m-d H:i:s",$v['add_time']);
			}
			if(!empty($v['overdue_time'])){
				$info[$k]['overdue_time']=date("Y-m-d H:i:s",$v['overdue_time']);
			}
			if($v['status']==-1){
				$info[$k]['status']="已删除";
			}
			if($v['status']==0){
				$info[$k]['status']="未审核";
				$info[$k]['color']=0;//设定颜色
			}
			if($v['status']==1){
				$info[$k]['status']="审核通过";
			}
			if($v['status']==2){
				$info[$k]['status']="审核未通过";
			}
		}
        if(!empty($info)){
            $data['total']=$count;
            $data['rows']=$info;
        }else{
            $data['total']=0;
            $data['rows']=0;
        }
        return $data;
	}
	//ajax调用CheckInputFunc验证字段在表中是否重复
	//$table 表名
	//$field 表对应需要验证的字段名
	//@author 李飞
	function tableCheckInputFunc($table,$field,$CnName, $name, $CheckType, $default = NULL, $LengMin = 0, $LengMax = 0){
		
		$m=M($table,C('DB_PRS'),C('DB_DEPOT'));
		if(!IS_POST) exit;
		$res=CheckInputFunc($CnName, $name, $CheckType, $default = NULL, $LengMin = 0, $LengMax = 0);
		if($res['ok']==false){
			$this->error($res['error']);
		}
		$map[$field]=$res['data'];
		$result=$m->where($map)->find();
		if($result){
            $return['status']=false;
            $return['id']=$result['id'];
        }else{
            $return['status']=true;
            $return['id']='0';
        }
        return $return;
	}
	//审核模型数据
	//$table 表名
    function tableExamine($table){
		
		$m=M($table,C('DB_PRS'),C('DB_DEPOT'));
        if(!IS_POST) exit;  
        $id=I('id');
		$value=I('value');
        if(empty($id)) exit;//为空
        $arr=explode(',', $id);
        $map['id']=array('in',$arr);
		if($value==1){
			$data['status']=1;
		}else if($value==2){
			$data['status']=2;
		}else{
			$return['message']='审核状态参数错误!';
            $return['status']=false;
			$this->ajaxReturn($return);
			exit;
		}
		$data['examine_time']=time();
        $result=$m->where($map)->save($data);
		// echo $m->getlastsql();
		// die;
        if(!$result){
            $return['message']='审核失败!';
            $return['status']=false;  
        }else{
             $return['message']='审核成功!';
             $return['status']=true; 
        }        
       return $return;
    }
	//删除模型数据
	//$table 表名
    function tableDel($table){
		
		$m=M($table,C('DB_PRS'),C('DB_DEPOT'));
        if(!IS_POST) exit;
        $id=I('id');
        if(empty($id)) exit;//为空
        $arr=explode(',', $id);
        $map['id']=array('in',$arr);
        $result=$m->where($map)->setField('status',-1);
        if(!$result){
            $return['message']='删除失败!';
            $return['status']=false;  
        }else{
            $return['message']='删除成功!';
            $return['status']=true; 
        }
        return $return;
    }
	//清空回收站
	//$table 表名
    function tableClear($table){
		
		$m=M($table,C('DB_PRS'),C('DB_DEPOT'));
        if(!IS_POST) exit;
        $id=I('id');
        if(empty($id)) exit;//为空
        $arr=explode(',', $id);
        $map['id']=array('in',$arr);
		$list=$m->where($map)->select();
		foreach($list as $k=>$v){
			if($v['status']<>-1){
				$return['message']='数据id'.$v['id'].'不在回收站不能清除，请进入回收站执行清空操作';
				$return['status']=false;
				return $return;
				exit;
			}
		}
        $result=$m->where($map)->delete();
        if(!$result){
            $return['message']='清空失败!';
            $return['status']=false;  
        }else{
            $return['message']='清空成功!';
            $return['status']=true;
        }
        return $return;
    }
	//恢复回收站数据
	//$table 表名
    function tableUndo($table){
		
		$m=M($table,C('DB_PRS'),C('DB_DEPOT'));
        if(!IS_POST) exit;
        $id=I('id');
        if(empty($id)) exit;//为空
        $arr=explode(',', $id);
        $map['id']=array('in',$arr);
		$list=$m->where($map)->select();
		foreach($list as $k=>$v){
			if($v['status']<>-1){
				$return['message']='数据id'.$v['id'].'不在回收站不能清除，请进入回收站执行清空操作';
				$return['status']=false;
				return $return;
				exit;
			}
		}
		$result=$m->where($map)->setField('status',0);
        if(!$result){
            $return['message']='恢复失败!';
            $return['status']=false;  
        }else{
            $return['message']='恢复成功!';
            $return['status']=true;
        }
        return $return;
    }
	//erp企业列表
	function erplist(){
		
		// $list=M('Erp',C('DB_PRS'),C('DB_DEPOT'))->where(array('status'=>array('neq',-1)))->select();
		$list=M('Erp',C('DB_PRS'),C('DB_DEPOT'))->where(array('status'=>1))->select();
		$arr[0]['id']=0;
		$arr[0]['name']='未选择';
		foreach($list as $k=>$v){
			$arr[$k+1]=$v;
		}
		return $arr;
	}
	//库位列表
    function storage_list(){
		
		$m=M('Storage',C('DB_PRS'),C('DB_DEPOT'));
		$map['state']=1;
		$list=$m->field('storage_code as id,name')->where($map)->select();
		$arr[0]['id']=0;
		$arr[0]['name']='未选择';
		foreach($list as $k=>$v){
			$arr[$k+1]=$v;
		}
		return $arr;
	}
	//产销国列表
	function countrylist(){
		
		$m=M('Country',C('DB_PRS'),C('DB_DEPOT'));
		$list=$m->field('country_code,country_name')->select();
		$arr[0]['country_code']=0;
		$arr[0]['country_name']='未选择';
		foreach($list as $k=>$v){
			$arr[$k+1]=$v;
		}
		return $arr;
	}
	//币制列表
	function coinlist(){
		
		$m=M('Coin',C('DB_PRS'),C('DB_DEPOT'));
		$list=$m->field('coin_code,coin_name')->select();
		$arr[0]['coin_code']=0;
		$arr[0]['coin_name']='未选择';
		foreach($list as $k=>$v){
			$arr[$k+1]=$v;
		}
		return $arr;
	}
	//单位列表
	function unitlist(){
		
		$m=M('Unit',C('DB_PRS'),C('DB_DEPOT'));
		$list=$m->field('unit_no,unit_name')->select();
		$arr[0]['unit_no']=0;
		$arr[0]['unit_name']='未选择';
		foreach($list as $k=>$v){
			$arr[$k+1]=$v;
		}
		return $arr;
	}
	//部门列表
	function sectionlist(){
		
		$m=M('Section',C('DB_PRS'),C('DB_DEPOT'));
		$list=$m->field('no,name')->where(array('status'=>1))->select();
		$arr[0]['no']=0;
		$arr[0]['name']='未选择';
		foreach($list as $k=>$v){
			$arr[$k+1]=$v;
		}
		// dump($arr);
		return $arr;
	}
	//员工列表
	function personnellist(){
		
		$m=M('Personnel',C('DB_PRS'),C('DB_DEPOT'));
		$list=$m->field('no,name')->where(array('status'=>1))->select();
		$arr[0]['no']=0;
		$arr[0]['name']='未选择';
		foreach($list as $k=>$v){
			$arr[$k+1]=$v;
		}
		return $arr;
	}
	//往来单位列表
	function contactsCompanylist(){
		
		$m=M('ContactsCompany',C('DB_PRS'),C('DB_DEPOT'));
		$list=$m->field('no,name')->where(array('status'=>1))->select();
		$arr[0]['no']=0;
		$arr[0]['name']='未选择';
		foreach($list as $k=>$v){
			$arr[$k+1]=$v;
		}
		return $arr;
	}
	//出入库类别列表
	function boundcatelist($bound_cate_code=1){//默认入库 1-入库类型2-出库类型
		
		$m=M('BoundCate',C('DB_PRS'),C('DB_DEPOT'));
		if($bound_cate_code==2){
			$map['bound_cate_code']=2;
		}else{
			$map['bound_cate_code']=$bound_cate_code;
		}
		$list=$m->field('code,name')->where($map)->select();
		$arr[0]['code']=0;
		$arr[0]['name']='未选择';
		foreach($list as $k=>$v){
			$arr[$k+1]=$v;
		}
		return $arr;
	}
	//账册列表
	function manua_idlist(){
		
		$m=M('BooksCate',C('DB_PRS'),C('DB_DEPOT'));
		$map['status']=1;
		$list=$m->field('code,name')->where($map)->select();
		foreach($list as $k=>$v){
			$arr[$k+1]=$v;
		}
		return $arr;
	}
	//账册列表
	function manuallist(){
		
		$m=M('BooksCate',C('DB_PRS'),C('DB_DEPOT'));
		$map['status']=1;
		$list=$m->field('code')->where($map)->select();
		$arr[0]['code']=0;
		$arr[0]['name']='未选择';
		foreach($list as $k=>$v){
			$arr[$k+1]['code']=$v['code'];
			$arr[$k+1]['name']=$v['code'];
		}
		return $arr;
	}
	//仓库列表
	function depot_list(){
		$m=M('Warehouse');
		// $map['status']=1;
		$list=$m->field('warehouse_code,name')->group('warehouse_code')->select();
		$arr[0]['code']=0;
		$arr[0]['name']='未选择';
		foreach($list as $k=>$v){
			$arr[$k+1]['code']=$v['warehouse_code'];
			$arr[$k+1]['name']=$v['name'];
		}
		return $arr;
	}
	//规则列表//二级
	function authrulelist(){
		
		$m=M('AuthRule',C('DB_PRS'),C('DB_DEPOT'));
		$map['status']=1;
		$map['pid']=0;
        $list=$m->where($map)->field('id,pid,title')->order('o')->select();//查询模块信息 
		$arr[0]['code']=0;
		$arr[0]['name']='未选择';
		foreach($list as $k=>$v){
			$arr[]['code']=$v['id'];
			$arr[]['name']=$v['title'];
			$lists=$m->where(array('status'=>1,'pid'=>$v['id']))->field('id,pid,title')->order('o')->select();//查询模块信息 
			foreach($lists as $key=>$value){
				$arr[]['code']=$value['id'];
				$arr[]['name']='&nbsp;&nbsp;|'.$value['title'];
			}
		}
		return $arr;
	}
	
	//拦截key列表
	function interceptkeylist(){
		
		$m=M('InterceptKey',C('DB_PRS'),C('DB_DEPOT'));
		$map['status']=1;
		$list=$m->field('name,field_name')->where($map)->select();
		$arr[0]['code']=0;
		$arr[0]['name']='未选择';
		foreach($list as $k=>$v){
			$arr[$k+1]['code']=$v['field_name'];
			$arr[$k+1]['name']=$v['name'];
		}
		return $arr;
	}
	
	//流水号
	function serialNumber($tablename){
		
		$m=M($tablename,C('DB_PRS'),C('DB_DEPOT'));
		//当日流水号生成
		$map['_string']="add_time-UNIX_TIMESTAMP(DATE(NOW()))>0 and add_time-UNIX_TIMESTAMP(DATE(NOW()))<86400";
		$count=$m->where($map)->count();//当天添加的采购单数
		// dump(C());
		// echo $m->getlastsql();
		// die;
		$count=$count+1;
		$serial_number="";
		if($count<10){
			$serial_number='0000'.strval($count);
		}
		if($count>=10 and $count<100){
			$serial_number='000'.$count;
		}
		if($count>=100 and $count<1000){
			$serial_number='00'.$count;
		}
		if($count>=1000 and $count<10000){
			$serial_number='0'.$count;
		}
		return $serial_number;//流水序号
	}

	function alert($flag,$data){
		echo json_encode(array('flag'=>$flag,'data'=>$data));
		exit;
	}
	//计算时间差/两个时间日期相隔的天数,时,分,秒.
	function timediff($begin_time,$end_time)
	{
		if($begin_time < $end_time) {
			$starttime = $begin_time;
			$endtime = $end_time;
		} else {
			$starttime = $end_time;
			$endtime = $begin_time;
		}
		$timediff = $endtime - $starttime;
		$days = intval( $timediff / 86400 );
		$remain = $timediff % 86400;
		$hours = intval( $remain / 3600 );
		$remain = $remain % 3600;
		$mins = intval( $remain / 60 );
		$secs = $remain % 60;
		$res = array( "day" => $days, "hour" => $hours, "min" => $mins, "sec" => $secs );
		return $res;
	}
/**
 * 字符串截取，支持中文和其他编码
 * @static
 * @access public
 * @param string $str 需要转换的字符串
 * @param string $start 开始位置
 * @param string $length 截取长度
 * @param string $charset 编码格式
 * @param string $suffix 截断显示字符
 * @return string
 */
function msubstr($str, $start=0, $length, $charset="utf-8", $suffix=true) {
    if(function_exists("mb_substr"))
        $slice = mb_substr($str, $start, $length, $charset);
    elseif(function_exists('iconv_substr')) {
        $slice = iconv_substr($str,$start,$length,$charset);
        if(false === $slice) {
            $slice = '';
        }
    }else{
        $re['utf-8']   = "/[\x01-\x7f]|[\xc2-\xdf][\x80-\xbf]|[\xe0-\xef][\x80-\xbf]{2}|[\xf0-\xff][\x80-\xbf]{3}/";
        $re['gb2312'] = "/[\x01-\x7f]|[\xb0-\xf7][\xa0-\xfe]/";
        $re['gbk']    = "/[\x01-\x7f]|[\x81-\xfe][\x40-\xfe]/";
        $re['big5']   = "/[\x01-\x7f]|[\x81-\xfe]([\x40-\x7e]|\xa1-\xfe])/";
        preg_match_all($re[$charset], $str, $match);
        $slice = join("",array_slice($match[0], $start, $length));
    }
    return $suffix ? $slice.'...' : $slice;
}

	//excel导出方法
	function exportExcel($expTitle,$expCellName,$expTableData){
			$xlsTitle = iconv('utf-8', 'gb2312', $expTitle);//文件名称
			$fileName = $xlsTitle.date('_YmdHis');//or $xlsTitle 文件名称可根据自己情况设定
			$cellNum = count($expCellName);
			$dataNum = count($expTableData);
			//vendor("PHPExcel.PHPExcel");
		   
			//导入PHPExcel类库，因为PHPExcel没有用命名空间，只能inport导入
			import("Org.Util.PHPExcel");
			import("Org.Util.PHPExcel.Writer.Excel5");
			import("Org.Util.PHPExcel.IOFactory.php");
		   
		   $date = date("Y_m_d",time());
			$fileName .= "_{$date}.xls";

			//创建PHPExcel对象，注意，不能少了\
			$objPHPExcel = new \PHPExcel();
			//$objProps = $objPHPExcel->getProperties();
			
			//$objPHPExcel = new PHPExcel();
			$cellName = array('A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z','AA','AB','AC','AD','AE','AF','AG','AH','AI','AJ','AK','AL','AM','AN','AO','AP','AQ','AR','AS','AT','AU','AV','AW','AX','AY','AZ');
			
			$objPHPExcel->getActiveSheet(0)->mergeCells('A1:'.$cellName[$cellNum-1].'1');//合并单元格
		    $objPHPExcel->setActiveSheetIndex(0)->setCellValue('A1', $expTitle);
			for($i=0;$i<$cellNum;$i++){
				$objPHPExcel->setActiveSheetIndex(0)->setCellValue($cellName[$i].'2', $expCellName[$i][1]); 
			}
			  // Miscellaneous glyphs, UTF-8   
			for($i=0;$i<$dataNum;$i++){
			  for($j=0;$j<$cellNum;$j++){
				$objPHPExcel->getActiveSheet(0)->setCellValue($cellName[$j].($i+3), ' '.$expTableData[$i][$expCellName[$j][0]]);
			  }             
			}  
			
			header('pragma:public');
			header('Content-type:application/vnd.ms-excel;charset=utf-8;name="'.$xlsTitle.'.xls"');
			header("Content-Disposition:attachment;filename=$fileName.xls");//attachment新窗口打印inline本窗口打印
			$objWriter = \PHPExcel_IOFactory::createWriter($objPHPExcel, 'Excel5');  
			$objWriter->save('php://output'); 
			exit;   
	}
	//隐藏部分用户名
	//$str = "如来神掌";
	//echo cut_str($str, 1, 0).'**'.cut_str($str, 1, -1);
	//输出：如**掌
	function cut_str($string, $sublen, $start = 0, $code = 'UTF-8')
	{
		 if($code == 'UTF-8')
		 {
			 $pa = "/[\x01-\x7f]|[\xc2-\xdf][\x80-\xbf]|\xe0[\xa0-\xbf][\x80-\xbf]|[\xe1-\xef][\x80-\xbf][\x80-\xbf]|\xf0[\x90-\xbf][\x80-\xbf][\x80-\xbf]|[\xf1-\xf7][\x80-\xbf][\x80-\xbf][\x80-\xbf]/";
			 preg_match_all($pa, $string, $t_string);

			if(count($t_string[0]) - $start > $sublen) return join('', array_slice($t_string[0], $start, $sublen));
			 return join('', array_slice($t_string[0], $start, $sublen));
		 }
		 else
		 {
			 $start = $start*2;
			 $sublen = $sublen*2;
			 $strlen = strlen($string);
			 $tmpstr = '';

			for($i=0; $i< $strlen; $i++)
			 {
				 if($i>=$start && $i< ($start+$sublen))
				 {
					 if(ord(substr($string, $i, 1))>129)
					 {
						 $tmpstr.= substr($string, $i, 2);
					 }
					 else
					 {
						 $tmpstr.= substr($string, $i, 1);
					 }
				 }
				 if(ord(substr($string, $i, 1))>129) $i++;
			 }
			 //if(strlen($tmpstr)< $strlen ) $tmpstr.= "...";
			 return $tmpstr;
		 }
	}
	function outboundcatelist(){
		$m=M('OutboundCate',C('DB_PRS'),C('DB_DEPOT'));
		$arr=$m->select();
		foreach($arr as $k=>$v){
			$arr[$k]['add_time']=date('Y-m-d H:i:s',$v['add_time']);
			$arr[$k]['update_time']=date('Y-m-d H:i:s',$v['update_time']);
			$arr[$k]['examine_time']=date('Y-m-d H:i:s',$v['examine_time']);
		}
		return $arr;
	}
	//按批次号冻结库存
	//ao_info批次详情
	//vs订单商品详情
	//自动关联批次库存
	function freez_storage($vs=array(),$times=1){
		$ao=M('ArrivalOrder',C('DB_PRS'),C('DB_DEPOT'));//商品详情入库单
		$pog=M('Pushordergoods',C('DB_PRS'),C('DB_DEPOT'));//订单详情表
		$freez=M('FreezLog',C('DB_PRS'),C('DB_DEPOT'));//冻结记录表
		$rule_freez=C('base_config.rule_freez');
        if($rule_freez){
            $orderby="overdue_time";
        }else {
            $orderby = "add_time";
        }
		$ao_info=$ao->where(array('goods_no'=>$vs['goods_no'],'inbound_status'=>1,'grounding_status'=>1,'storage_amount'=>array('GT',0)))->order($orderby.' asc')->limit(1)->find();//按商品入库批次顺序冻结库存
		
		if(empty($ao_info)){
			if($times>1){
				$return['message']="商品编码为[".$vs['goods_no']."]的库存不足！";
			}else{
				$return['message']="商品编码为[".$vs['goods_no']."]的库存不足或者没有此编码,请检查！";
			}
			$return['status']=false;
			return $return;
		}else{
			if($ao_info['storage_amount']==0){
				$return['message']="商品编码为[".$vs['goods_no']."]的库存不足！";
				$return['status']=false;
				return $return;
			}
		}
		$map_ao['id']=$ao_info['id'];//条件
		if($ao_info['storage_amount']>=$vs['goods_nums']){//剩余库存大于等于订单商品数量
			$data_ao['freez_amount']=array('exp','freez_amount+'.$vs['goods_nums']);//冻结数量
			$data_ao['storage_amount']=array('exp','storage_amount-'.$vs['goods_nums']);//更新库存
			$res_ao=$ao->where($map_ao)->save($data_ao);
            $freez->add(array('goods_id'=>$map_ao['id'],'freez_amount'=>$vs['goods_nums'],'goods_no'=>$vs['goods_no'],'storage_amount'=>$data_ao['storage_amount'],'time'=>time(),'times'=>$times));
			
			$map_pog['id']=$vs['id'];
			$str=$ao_info['id'].':'.$vs['goods_nums'];
			$data_pog['goods_batch_no']=array('exp',"concat(ifnull(goods_batch_no,''),',$str')");//关联批次和数量
			$pog->where($map_pog)->save($data_pog);
			// echo $pog->getlastsql();
			// die;
			$return['message']="更新成功";
			$return['status']=true;
			return $return;
		}else{
			$data_ao['freez_amount']=array('exp','freez_amount+'.$ao_info['storage_amount']);//冻结数量
			$data_ao['storage_amount']=0;//更新库存
			$res_ao=$ao->where($map_ao)->save($data_ao);
			
			$map_pog['id']=$vs['id'];
			$str=$ao_info['id'].':'.$ao_info['storage_amount'];
			$data_pog['goods_batch_no']=array('exp',"concat(ifnull(goods_batch_no,''),',$str')");//关联批次和数量
			$pog->where($map_pog)->save($data_pog);
			// echo $pog->getlastsql();
			// die;
			$vs['goods_nums']=$vs['goods_nums']-$ao_info['storage_amount'];//剩余数量
			return freez_storage($vs,++$times);//递归调用
		}
	}
	function push($url,$post_data){
		
		$ch = curl_init();
		curl_setopt($ch, CURLOPT_URL, $url);
		curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
		curl_setopt($ch, CURLOPT_POST, 1);
		curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($post_data));
		
		$output = curl_exec($ch);
		// dump($output);
		// die;
		curl_close($ch);
		return $output;
	}
	
	function send_curl($url,$data){
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        //post传值数据
        curl_setopt($ch, CURLOPT_POST, 1);
        //post的变量
        curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query(array('data'=>json_encode($data))));
        $output = curl_exec($ch);
		// dump($output);
		// die;
        curl_close($ch);
        return $output;
    }
	//按批次号冻结库存
	//ao_info批次详情
	//vs订单商品详情
	//$times:调用次数
	//自动关联批次库存
	//$str:批次详情关联信息
	function freez_storage_erp($vs=array(),$times=1,$str='',$agent_id=0){
		$ao=M('ArrivalOrder',C('DB_PRS'),C('DB_DEPOT'));//商品详情入库单
		$d=M('DistributionPeople');
        $freez=M('FreezLog',C('DB_PRS'),C('DB_DEPOT'));//冻结记录表
		
		$ao_storage=$ao->field('sum(storage_amount) storage_amount')->where(array('goods_no'=>$vs['goods_no'],'inbound_status'=>1))->select();
		$storage_amount=$ao_storage[0]['storage_amount'];//剩余库存

		if(!empty($agent_id)){//代销商
			// $api_url="http://erpvr.jm.com/index.php/Company/Api/get_storage_config";//测试-获取代销商商品价格、预警库存配置信息
			$api_url="http://www.t-cang.com/erpts/index.php/Company/Api/get_storage_config";//获取代销商商品价格、预警库存配置信息
			$push_data=array();
			// $push_data['erp_code']=48;//测试erp_code
			$push_data['erp_code']=37;
			$push_data['goods_no']=$vs['goods_no'];
			$push_data['distribution_department_id']=$d->where(array('id'=>$agent_id))->getField('department_id');
			$res_push=push($api_url,$push_data);
			$res_push=json_decode($res_push,true);

			if(empty($res_push['data']['storage_alert_amount_config'])){
				$return['message']="没有找到[".$vs['goods_no']."]配置的商品库存信息！";
				$return['status']=false;
				return $return;
			}else{
				$storage_amount=$storage_amount-$res_push['data']['storage_alert_amount_config']-$vs['goods_nums'];
			}
		}

		if($storage_amount<0){
			$return['message']="商品编码[".$vs['goods_no']."]的商品库存不足！";
			$return['status']=false;
			return $return;
		}
		$rule_freez=C('base_config.rule_freez');
        if($rule_freez){
            $orderby="overdue_time";
        }else{
            $orderby="add_time";
        }
		$ao_info=$ao->where(array('goods_no'=>$vs['goods_no'],'inbound_status'=>1,'grounding_status'=>1,'storage_amount'=>array('GT',0)))->order($orderby.' asc')->limit(1)->find();//按商品入库批次顺序冻结库存
		file_put_contents('./log/times.log',date('Y-m-d H:i:s').var_export($times,true).PHP_EOL,FILE_APPEND);//日志导出sql
		if(empty($ao_info)){
			if($times>1){
				$return['message']="商品编码为[".$vs['goods_no']."]的库存不足！";
			}else{
				$return['message']="商品编码为[".$vs['goods_no']."]的库存不足或者没有此编码,请检查！";
			}
			$return['status']=false;
			return $return;
		}else{
			if($ao_info['storage_amount']==0){
				$return['message']="商品编码为[".$vs['goods_no']."]的库存不足！";
				$return['status']=false;
				return $return;
			}
		}
		
		$map_ao['id']=$ao_info['id'];//条件

		if($ao_info['storage_amount']>=$vs['goods_nums']){//剩余库存大于等于订单商品数量
			$data_ao['freez_amount']=array('exp','freez_amount+'.$vs['goods_nums']);//冻结数量
			$data_ao['storage_amount']=array('exp','storage_amount-'.$vs['goods_nums']);//更新库存
			$res_ao=$ao->where($map_ao)->save($data_ao);

            $freez->add(array('goods_id'=>$map_ao['id'],'freez_amount'=>$vs['goods_nums'],'goods_no'=>$vs['goods_no'],'storage_amount'=>$data_ao['storage_amount'],'time'=>time(),'times'=>$times));
			
			$str=$str.','.$ao_info['id'].':'.$vs['goods_nums'];


			$return['message']="更新成功";
			$return['detail']['goods_detail_id']=$vs['goods_detail_id'];
			$return['detail']['str']=$str;
			$return['status']=true;
			return $return;
		}else{
			$data_ao['freez_amount']=array('exp','freez_amount+'.$ao_info['storage_amount']);//冻结数量
			$data_ao['storage_amount']=0;//更新库存
			$res_ao=$ao->where($map_ao)->save($data_ao);
			$vs['goods_nums']=$vs['goods_nums']-$ao_info['storage_amount'];//剩余数量

			$str=$str.','.$ao_info['id'].':'.$ao_info['storage_amount'];															
			return freez_storage_erp($vs,++$times,$str);//递归调用
		}
	}
	//查看费用并扣费
	//$feelist_id  费用名称对应id（关联自动扣费节点）
	//$out_money_nums  要扣费节点对应数量
	//扣erp企业费用(扣仓库会员费用--待定)
	function out_money($feelist_id,$out_money_nums,$erp_code){
		$Member=M('Member');
		$User=M('User');
		$Feerule=M('Feerule');
		$Feelist=M('Feelist');
		$Feelog=M('Feelog');
		//根据erp_code确定会员信息-begin
		$user_info=$User->where(array('id'=>$erp_code))->find();
		$member_info=$Member->where(array('id'=>$user_info['member_id']))->find();
		//根据erp_code确定会员信息-end
		
		$feerule_info=$Feerule->where(array('id'=>$user_info['feerule_id']))->find();
		$group_arr=explode(':',$feerule_info['group_id']);
		
		$feelist_idarr=explode(',',$group_arr[0]);
		$price_arr=explode(',',$group_arr[1]);
		$cate_arr=explode(',',$group_arr[2]);
		$key=array_search($feelist_id,$feelist_idarr);//匹配对应键值，返回对应键名
		
		if($key){//存在扣费节点
			$out_money_cate=$cate_arr[$key];//扣费类型1：元/单 2:元/件
			$out_money_price=$price_arr[$key];//扣费金额
			if($out_money_cate==1){//元/单
				$out_money_nums=1;
			}
			$outbound_money=$out_money_nums*$out_money_price;//总扣费金额

			if($member_info['money']-$member_info['out_money']-$outbound_money>0){//余额大于要扣费金额
				$data_member['out_money']=array('exp','out_money+'.(int)$outbound_money);
				$res_member=$Member->where(array('id'=>$user_info['member_id']))->save($data_member);
				if($res_member===false){
					$return['status']=0;
					$return['message']='扣费失败！';
					$this->ajaxReturn($return);
				}else{
					$feelist_info=$Feelist->where(array('id'=>$feelist_id))->find();
					$data_log['cate_id']=$out_money_cate;//扣费类型id
					$data_log['feecate_id']=$feelist_info['feecate'];//费用类型id
					$data_log['feerule_id']=$user_info['feerule_id'];//费用规则id
					$data_log['count_price']=$outbound_money;//扣费金额
					$data_log['feelist_id']=$feelist_id;//扣费费用名称id
					$data_log['out_money_nums']=$out_money_nums;//扣费数量
					$data_log['member_id']=$user_info['member_id'];//扣费的会员id
					$data_log['cate']=1;//1为自动扣费
					$data_log['add_time']=time();
					$res_feelog=$Feelog->add($data_log);//更新扣费记录
					if(!$res_feelog){
						$return['status']=0;
						$return['message']='增加扣费日志失败！';
						$this->ajaxReturn($return);
					}
				}
			}else{
				$return['status']=0;
				$return['message']='余额不足！';
				$this->ajaxReturn($return);
			}
		}
	}
	//仓储费(月租金)
	function month_rent($erp_code){
		$u=M('User');
		$w=M('Warehouse');
		$uw=M('UserWarehouse');
		$user_info=$u->where(array('id'=>$erp_code))->find();
		$uw_info=$uw->where(array('user_id'=>$erp_code))->find();
		$warehouse_list=explode(',',$uw_info['warehouse_group_id']);
		foreach($warehouse_list as $k=>$v){
			$warehouse_info=$w->where(array('id'=>$v))->find();
			if($warehouse_info['warehouse_cate']==1){//一般仓
				
			}
			if($warehouse_info['warehouse_cate']==2){//跨境（保税）仓
				
			}
		}
	}
	//一般仓月租金
	//$area占地面积
	//start_time  开始时间（时间戳）
	//end_time	结束时间（时间戳）
	//自然月
	function month_rent_normal($area,$start_time,$end_time){
		$end_time=date('Y-m-d',$end_time);
		$start_time=date('Y-m-d',$start_time);
		$monthNums=getMonthNum($start_time,$end_time);
		$month_rent=$area*12.5*$monthNums;//月租金=12.5元/m2/自然月
		return $month_rent;
	}
	//跨境（保税）仓月租金
	//$area占地面积
	//start_time  开始时间（时间戳）
	//end_time	结束时间（时间戳）
	//自然月
	function month_rent_cross($area,$start_time,$end_time){
		$start_time+=86400*45;//开始计费日期，入库后45天
		$the_day=date('d',$start_time);//当前日期(天)
		$next_month_day=date('Y-m-'.$the_day,$end_time);//下月日期（同一天）
		//月租金=天数*1元*m2
		
		
		$monthNums=getMonthNum($start_time,$end_time);
		$month_rent=$area*12.5*$monthNums;//月租金=12.5元/m2/自然月
		return $month_rent;
	}
	/**  
	* @var date1 开始日期
	* @var date2 结束日期
	* @var tags 年月日之间的分隔符标记,默认为'-'  
	* @return 相差的月份数量
	* @example: $date1 = "2003-08-11"; $date2 = "2008-11-06"; $monthNum = getMonthNum( $date1 , $date2 ); echo $monthNum; 
	*/
	function getMonthNum( $date1, $date2, $tags='-' ){  
		$date1 = explode($tags,$date1);  
		$date2 = explode($tags,$date2);
		return abs(($date2[0] - $date1[0]) * 12 + ($date2[1] - $date1[1])); 
	}
	//相差天数
	//start_time  开始时间（时间戳）
	//end_time  结束时间（时间戳）
	function count_days($start_time,$end_time){
		return round(abs($end_time-$start_time)/86400);
	}
	//返回json
	function alert_json($status,$message,$info=false){
		header('Content-Type:application/json; charset=utf-8');
		if($info){
			$return['info']=$message;
		}else{
			$return['message']=$message;
		}
		$return['status']=$status;
		exit(json_encode($return,0));
	}
	//电话验证,形如(xxxx-xxxxxxxx)
	function isTel($tel){
		$isTel="/^([0-9]{3,4}-)?[0-9]{7,8}$/";
		if(preg_match($isTel,$tel)){
			return 1;
		}else{
			return 0;
		}
	}
//二维数组值匹配
//$value:要匹配的值
//$array:要匹配的数组
function deep_in_array($value,$array) {   
	foreach($array as $item){
		if(!is_array($item)){
			if($item == $value){
				return true;  
			}else{
				continue;   
			}  
		}
		if(in_array($value, $item)) {  
			return true;      
		} else if(deep_in_array($value, $item)) {  
			return true;      
		}  
	}   
	return false;   
}

//ems费用计算
//$ems_company:快递公司名称
//$area:地区
//$weight:重量
//$merchant_code:商家编码
function make_emsfee($ems_company,$area,$weight,$merchant_code=''){
	$m=M('EmsCompany',C('DB_PRS'),C('DB_DEPOT'));
	$n=M('EmsFee',C('DB_PRS'),C('DB_DEPOT'));
	$p=M("Packing",C('DB_PRS'),C('DB_DEPOT'));
	if(empty($merchant_code)){//默认快递模板
		$m_info=$m->where(array('name'=>array('like',"%$ems_company%"),'default_status'=>1))->find();
	}else{
		$m_info=$m->where(array('name'=>array('like',"%$ems_company%"),'left(merchant_code,9)'=>$merchant_code))->find();
	}
	if(empty($m_info) and empty($merchant_code)){
		$return['status']=0;
		$return['message']='没找到对应的快递公司['.$ems_company.']';
		return $return;
	}
	if(empty($m_info) and !empty($merchant_code)){
		$return['status']=0;
		$return['message']='商家编码['.$merchant_code.']没找到对应的快递公司['.$ems_company.']';
		return $return;
	}
	$area=msubstr($area,0,2,"utf-8",false);
	$n_info=$n->where(array('area'=>array('like',"%$area%"),array('ems_code'=>$m_info['code'])))->find();
	
	if(empty($n_info) and empty($merchant_code)){
		$return['status']=0;
		$return['message']='快递公司['.$ems_company.'],地区['.$area.']没找到对应的费用模板';
		return $return;
	}
	if(empty($n_info) and !empty($merchant_code)){
		$return['status']=0;
		$return['message']='商家编码['.$merchant_code.']对应快递公司['.$ems_company.'],地区['.$area.']没找到对应的费用模板';
		return $return;
	}
	$split_weight=$m_info['weight'];//快递计费 重量段  IF(D2>3,F2+(D2-3)*G2,F2+(E2-1)*G2)
	if($split_weight<$weight){//重量段后计费规则
		$first_weight	=$n_info['first_weight_t'];//首重单位数量
		$second_weight	=$n_info['second_weight_t'];//续重单位数量
		$first_price	=$n_info['first_price_t'];//首重单位价格
		$second_price	=$n_info['second_price_t'];//续重单位价格
		
		$remain_weight=$weight-$first_weight;//续重重量
		$remain_price=ceil($remain_weight/$second_weight)*$second_price;
		$data['fee']=$first_price+$remain_price;
	}else{//重量段前计费规则
		$first_weight	=$n_info['first_weight'];
		$second_weight	=$n_info['second_weight'];
		$first_price	=$n_info['first_price'];
		$second_price	=$n_info['second_price'];
		
		if($weight<=$first_weight){//重量小于首重计费,按首重计费
			$data['fee']=$first_price;
		}else{
			$remain_weight=$weight-$first_weight;//续重重量
			$remain_price=ceil($remain_weight/$second_weight)*$second_price;
			$data['fee']=$first_price+$remain_price;
		}
	}
	$return['status']=1;
	$return['message']="生成快递费用成功";
	$return['fee']=$data['fee'];
	return $return;
}


/* 2019.02.18
 * by 富春
 * 由于表中time格式为int,空值时date()处理后会显示1970-01-01影响业务展示，故int=0时显示''
 * 
 */
function timeTransfer($time=0,$format = 'Y-m-d H:i:s'){
    return (!$time)?'':date($format,$time);
}







